Split ObservableCacheEx.cs into per-family partial classes#1095
Merged
Conversation
Splits the 6800-line ObservableCacheEx.cs into 24 smaller partial-class files grouped by operator family. Each method (and all of its overloads) lives in exactly one file. No code, comments, or XML documentation is added, removed, or otherwise modified; this is a pure file reorganization. All 2218 tests pass.
Splits the monolithic ObservableCacheEx.cs into 19 smaller partial-class files grouped by operator family. The two pre-existing partials (ObservableCacheEx.SortAndBind.cs, ObservableCacheEx.VirtualiseAndPage.cs) are untouched. Each method (and all of its overloads) lives in exactly one file. No code, XML documentation, comments, preprocessor directives, or constants are added, removed, or otherwise modified. The split was generated programmatically with byte-level per-method equality checks against the original.
…to rebased split
Sorts members alphabetically by name within each new partial file. Overloads of the same name preserve their original declaration order. Constants sort before methods. Pre-existing partials (SortAndBind, VirtualiseAndPage) are not modified.
JakenVeina
previously approved these changes
May 30, 2026
JakenVeina
requested changes
May 30, 2026
Collaborator
JakenVeina
left a comment
There was a problem hiding this comment.
Seriously, goddamnit, GitHub.
…oad set)
Addresses PR review feedback:
1. ONE FILE PER OPERATOR NAME (one overload set per file). The previous split
into 19 family files is replaced with 103 per-operator partial files,
matching the existing convention set by ObservableCacheEx.SortAndBind.cs
and ObservableCacheEx.VirtualiseAndPage.cs.
2. BARE ObservableCacheEx.cs FILE restored to carry the canonical class-level
XML documentation. All partials carry the same canonical class summary
('Extensions for dynamic data.') so SA1601 is satisfied and there are no
divergent per-file class docs. SortAndBind.cs and VirtualiseAndPage.cs
were also updated for consistency.
3. PRIVATE HELPERS placed AFTER all public members within their containing
file. Each private helper lives in the alphabetically-first operator file
that calls it:
- Combine -> And.cs (also called by Except, Or, Xor)
- ForForced -> Transform.cs (also called by TransformSafe)
- AdaptSelector -> Group.cs (also called by GroupOnObservable)
- OnChangeAction -> OnItemAdded.cs (also called by OnItem* family)
- TrueFor -> TrueForAll.cs (also called by TrueForAny)
- CreateChangeSetTransformer -> TransformManyAsync.cs (also called by TransformManySafeAsync)
- DefaultResortOnSourceRefresh const -> MergeManyChangeSets.cs
- DefaultSortResetThreshold const -> Sort.cs
The byte content of every method body is preserved (verified programmatically).
#if/#endif preprocessor regions (SUPPORTS_BINDINGLIST in Bind.cs,
SUPPORTS_ASYNC_DISPOSABLE around AsyncDisposeMany) are reconstructed in the
new files.
dwcullop
added a commit
to dwcullop/DynamicData
that referenced
this pull request
May 30, 2026
…ad set) Mirrors the same convention applied to ObservableCacheEx (PR reactivemarbles#1095): 1. ONE FILE PER OPERATOR NAME (one overload set per file). The previous 17 family files are replaced with 63 per-operator partial files. 2. BARE ObservableListEx.cs FILE restored to carry the canonical class-level XML documentation. All partials carry the same canonical class summary ('Extensions for ObservableList.') so SA1601 is satisfied and there are no divergent per-file class docs. 3. PRIVATE HELPERS placed AFTER all public members within their containing file. The 5 private 'Combine' overloads (used by And, Except, Or, Xor) are placed at the bottom of And.cs (alphabetically first caller). The byte content of every method body is preserved (verified programmatically).
JakenVeina
approved these changes
Jun 3, 2026
Per Jake's review feedback, private helpers used by multiple operators get their
own ObservableCacheEx.{HelperName}.cs file, matching the per-operator pattern
established for the public surface.
Combine -> ObservableCacheEx.Combine.cs (from And.cs)
AdaptSelector -> ObservableCacheEx.AdaptSelector.cs (from Group.cs)
OnChangeAction -> ObservableCacheEx.OnChangeAction.cs (from OnItemAdded.cs)
ForForced -> ObservableCacheEx.ForForced.cs (from Transform.cs)
CreateChangeSetTransformer -> ObservableCacheEx.CreateChangeSetTransformer.cs (from TransformManyAsync.cs)
TrueFor -> ObservableCacheEx.TrueFor.cs (from TrueForAll.cs)
DefaultSortResetThreshold const moved to ObservableCacheEx.cs (the core file).
Audit found it is used by both Sort and SortBy, contrary to the original PR body.
AsyncDisposeMany #if SUPPORTS_ASYNC_DISPOSABLE wrapping replaced with a project-level
Compile Remove. The file body is unconditionally compiled on supported platforms and
excluded entirely on unsupported ones (net4*).
All extractions are byte-preserving moves with no functional change. Builds clean on
all target frameworks (netstandard2.0, net462, net6-net10). Targeted tests pass.
dwcullop
added a commit
that referenced
this pull request
Jun 6, 2026
* Break ObservableListEx.cs into per-family partial classes Splits the 2900-line ObservableListEx.cs into 17 smaller partial-class files grouped by operator family. Each method (and all of its overloads) lives in exactly one file. The class declaration is changed to partial; no code, comments, or XML documentation is added, removed, or otherwise modified. All 2218 tests pass. * Rename Pagination to Virtualise and alphabetize list partial members Renames ObservableListEx.Pagination.cs to ObservableListEx.Virtualise.cs for closer parity with the cache equivalent (ObservableCacheEx.VirtualiseAndPage.cs). Sorts members alphabetically within each new partial file; overloads of the same name preserve their original declaration order. * Split ObservableListEx.cs partials into one file per operator (overload set) Mirrors the same convention applied to ObservableCacheEx (PR #1095): 1. ONE FILE PER OPERATOR NAME (one overload set per file). The previous 17 family files are replaced with 63 per-operator partial files. 2. BARE ObservableListEx.cs FILE restored to carry the canonical class-level XML documentation. All partials carry the same canonical class summary ('Extensions for ObservableList.') so SA1601 is satisfied and there are no divergent per-file class docs. 3. PRIVATE HELPERS placed AFTER all public members within their containing file. The 5 private 'Combine' overloads (used by And, Except, Or, Xor) are placed at the bottom of And.cs (alphabetically first caller). The byte content of every method body is preserved (verified programmatically). * Extract Combine private helpers into their own file Per Jake's review feedback, the five Combine private helpers (shared by And, Or, Except, Xor) move from ObservableListEx.And.cs to a dedicated ObservableListEx.Combine.cs, matching the per-operator pattern established for the public surface. Audit confirms Combine is the only multi-caller private helper in ObservableListEx partials. Byte-preserving move with no functional change. Library builds clean on all target frameworks.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Splits
ObservableCacheEx.cs(6,830+ lines, 100+ distinct operator names spanning 290 method bodies) into one partial-class file per operator name (overload set), following the convention already established byObservableCacheEx.SortAndBind.csandObservableCacheEx.VirtualiseAndPage.cs.This revision addresses the review feedback on the original family-grouping split:
ObservableCacheEx.Edit.cswith 27 operator names, etc.) are replaced with per-operator partial files. FindingAddOrUpdate.csis now exactly that.ObservableCacheEx.csrestored as a bare partial carrying the canonical class XML doc and theDefaultSortResetThresholdconst (shared betweenSortandSortBy). Every per-operator partial repeats the same canonical summary (Extensions for dynamic data.) so the documentation never diverges between files and SA1601 is satisfied.ObservableCacheEx.SortAndBind.csandObservableCacheEx.VirtualiseAndPage.cswere also updated for consistency.ObservableCacheEx.{HelperName}.csfile, matching the per-operator pattern for the public surface (per Jake's follow-up review).#if SUPPORTS_ASYNC_DISPOSABLElifted to the project level.ObservableCacheEx.AsyncDisposeMany.csis excluded from compilation via<Compile Remove>inDynamicData.csprojon platforms whereSUPPORTS_ASYNC_DISPOSABLEis not defined, instead of wrapping the file body in#if.This is still a pure file reorganisation. No code, no XML documentation, no comments, and no constants were added, removed, or altered. The byte content of every method body is preserved (verified programmatically against the original).
#if SUPPORTS_BINDINGLIST(around the BindingListBindoverloads) is reconstructed insideObservableCacheEx.Bind.cs.Private helper files
Each multi-caller private helper lives in its own
ObservableCacheEx.{HelperName}.csfile:Combine(5 overloads)ObservableCacheEx.Combine.csAnd,Except,Or,XorForForced(2 overloads)ObservableCacheEx.ForForced.csTransform,TransformSafeAdaptSelectorObservableCacheEx.AdaptSelector.csGroup,GroupOnObservableOnChangeAction(2 overloads)ObservableCacheEx.OnChangeAction.csOnItemAdded,OnItemRefreshed,OnItemRemoved,OnItemUpdatedTrueForObservableCacheEx.TrueFor.csTrueForAll,TrueForAnyCreateChangeSetTransformer(3 overloads)ObservableCacheEx.CreateChangeSetTransformer.csTransformManyAsync,TransformManySafeAsyncSingle-operator helpers stay with their operator:
DefaultResortOnSourceRefreshconst remains inObservableCacheEx.MergeManyChangeSets.cs. TheDefaultSortResetThresholdconst moves toObservableCacheEx.cs(the core file) because it is shared betweenSortandSortBy.Files
DefaultSortResetThresholdconst)SUPPORTS_ASYNC_DISPOSABLEis undefined)DefaultResortOnSourceRefreshconst)Touched pre-existing files
ObservableCacheEx.SortAndBind.csandObservableCacheEx.VirtualiseAndPage.cshad their class-level XML summaries replaced with the canonicalExtensions for dynamic data.text so all partials carry consistent documentation. No code in those files was changed.DynamicData.csprojgains a conditional<ItemGroup>that excludesObservableCacheEx.AsyncDisposeMany.csfrom compilation whenSUPPORTS_ASYNC_DISPOSABLEis not defined.Verification
The split was generated programmatically with byte-level per-method equality checks against the original. Every public method and every private helper used by the public surface was confirmed to be present in exactly one file. Builds clean on every target framework (netstandard2.0, net462, net6-net10). The full test suite passes (one pre-existing flaky concurrency test in
SuspendNotificationsFixtureis unrelated and fails onmaintoo).